﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// 二维文字表中列的对齐方式。
    /// </summary>
    public enum ColumnAlignment
    {
        LEFT, RIGHT, CENTER
    }

    /// <summary>
    /// 二维文字表文本行相关信息。
    /// </summary>
    public class TableLinesInfo
    {
        private bool isUsed = false;
        /// <summary>
        /// 表示是否已被处理过。
        /// </summary>
        public bool IsUsed
        {
            get { return this.isUsed; }
            set { this.isUsed = value; }
        }

        private String tableHtmlText = "";
        /// <summary>
        /// 生成的 Html 表格文本。
        /// </summary>
        public string TableHtmlText
        {
            get { return this.tableHtmlText; }
            set { this.tableHtmlText = value; }
        }

        private List<TableLine> tableLines = new List<TableLine>();
        /// <summary>
        /// 二维文字表各行文本。
        /// </summary>
        public List<TableLine> TableLines
        {
            get { return tableLines; }
            set { this.tableLines = value; }
        }

        public int ColumnDefinitionLinesCount
        {
            get
            {
                int c = 0;
                foreach (var tl in tableLines)
                {
                    if (tl.Type == TableLineType.ColumnDefinitionLine)
                    {
                        c++;
                    }
                }
                return c;
            }
        }

        public List<TableLine> HeaderLines
        {
            get
            {
                var headLines = new List<TableLine>();
                foreach (var tl in tableLines)
                {
                    if (tl.Type == TableLineType.ColumnDefinitionLine) break;

                    headLines.Add(tl);
                }
                return headLines;
            }
        }

        public List<TableLine> BodyLines
        {
            get
            {
                var bodyLines = new List<TableLine>();
                for (int i = tableLines.Count - 1; i >= 0; i--)
                {
                    var tl = tableLines[i];
                    if (tl.Type == TableLineType.ColumnDefinitionLine) break;

                    bodyLines.Add(tl);
                }
                return bodyLines;
            }
        }

        private List<ColumnAlignment> columnAlignments = new List<ColumnAlignment>();
        /// <summary>
        /// 二维文字表各列的对齐方式。
        /// </summary>
        public List<ColumnAlignment> ColumnAlignments
        {
            get { return columnAlignments; }
        }

        private int startLineIndex;
        /// <summary>
        /// 二维文字表从哪一行开始。
        /// </summary>
        public int StartLineIndex
        {
            get { return this.startLineIndex; }
            set { this.startLineIndex = value; }
        }

        private int endLineIndex;
        /// <summary>
        /// 二维文字表到哪一行结束。
        /// </summary>
        public int EndLineIndex
        {
            get { return this.endLineIndex; }
            set { this.endLineIndex = value; }
        }

        /// <summary>
        /// 需要合并到上一行的行尾由“|^”或“｜^”结尾。
        /// 第一行表格体即使末尾有^也不合并。
        /// 注意：此方法需要先对二维文字表进行格式化，确保表体各行的单元格数量是一致的。
        /// </summary>
        internal void PreviewFormatTableLines()
        {
            var trimChars = new char[] { ' ', '　', '\t' };

            int maxColumns = -1;

            //第一次循环，取出最多列
            for (int i = tableLines.Count - 1; i >= 0; i--)
            {
                var line = tableLines[i];
                if (line.LineText.EndsWith("|^") || line.LineText.EndsWith("｜^"))
                {
                    line.Type = TableLineType.MergeLine;
                    line.LineText = line.LineText.Substring(0, line.LineText.Length - 1);
                }

                line.LineText = line.LineText.Trim(trimChars);
                if (line.LineText.StartsWith("|") == false && line.LineText.StartsWith("｜") == false)
                    line.LineText = "｜" + line.LineText;

                if (line.LineText.EndsWith("|") == false && line.LineText.EndsWith("｜") == false)
                    line.LineText += "｜";

                line.LineText.Replace("|", "｜");

                maxColumns = Math.Max(maxColumns, CellsOfLine(line.LineText));
            }

            if (maxColumns <= 0) return;

            //根据最多的一列补全相关文本，从而便于实现向上合并行。
            int columnDefinitionLineIndex = -1;
            var splittor = new char[] { '｜', '|' };
            bool cdFinded = false;

            var cellBlankChars = new char[] { ' ', '　', '\t', };
            var cellMergeMarkChars = new char[] { ' ', '　', '\t', '^', };

            for (int i = tableLines.Count - 1; i >= 0; i--)
            {
                var line = tableLines[i];
                if (CustomMarkdownSupport.IsColumnAlignmentDefinitionLine(line.LineText))
                {
                    line.HeaderOrBodyType = HeaderOrBodyType.ColumnDifinition;
                    columnDefinitionLineIndex = i;
                    cdFinded = true;

                    //列定义行上面的行不在这里补全——这里只处理表体——表头不支持“向上合并行”
                    //break;
                    continue;
                    //2020年4月19日，改为也支持表头设置 Cells 内容。
                }

                if (cdFinded)
                {
                    line.HeaderOrBodyType = HeaderOrBodyType.HeaderLine;
                }
                else
                {
                    line.HeaderOrBodyType = HeaderOrBodyType.BodyLine;
                }

                string[] spans = line.LineText.Split(splittor);
                for (int j = 1; j <= spans.Length - 2; j++)     //因为必须以“｜”开头并结尾，所以切分出来以后，spans 首尾都是多余的
                {
                    line.Cells.Add(spans[j]);
                }

                //补全空单元格。
                for (int k = spans.Length; k < maxColumns; k++)
                {
                    line.Cells.Add("");   //这里只起标记作用，不能加空格字符等替代文本——必须是空字符串。
                }
            }

            //实现向上合并。
            for (int i = tableLines.Count - 1; i > Math.Max(columnDefinitionLineIndex, 0); i--)
            {
                if (i <= 0) break;                      //最前一行表体不需要合并

                var preLine = tableLines[i - 1];
                if (preLine.Type == TableLineType.ColumnDefinitionLine) break;

                var line = tableLines[i];
                if (line.Type != TableLineType.MergeLine) continue;

                for (int k = 0; k <= line.Cells.Count - 1; k++)
                {
                    if (string.IsNullOrWhiteSpace(line.Cells[k]) == false)
                    {
                        var cellspan = line.Cells[k].Trim(cellBlankChars);
                        if (cellspan.StartsWith("^") || cellspan.EndsWith("^"))
                        {
                            cellspan = cellspan.Trim(cellMergeMarkChars);
                            var preSpan = preLine.Cells[k].Trim(new char[] { ' ', '　', '\t', });
                            var preSpanShouldJoin = (preSpan.StartsWith("^") || preSpan.EndsWith("^"));

                            preLine.Cells[k] = (preSpanShouldJoin ? "^" : "") + preSpan.TrimEnd(cellMergeMarkChars) + $"{cellspan}";
                        }
                        else
                        {
                            preLine.Cells[k] += $"<Br/>{cellspan}";
                        }
                    }
                }

                tableLines.RemoveAt(i);       //合并之后就不需要再保留了。
            }

            for (int i = tableLines.Count - 1; i >= Math.Max(columnDefinitionLineIndex, 0); i--)
            {
                var line = tableLines[i];
                if (line.Type != TableLineType.ColumnDefinitionLine)
                    line.LineText = JoinCells(line.Cells);
            }
        }

        private string JoinCells(List<string> cells)
        {
            if (cells == null || cells.Count <= 0) return "";
            StringBuilder sb = new StringBuilder();
            sb.Append("｜");
            foreach (var cs in cells)
            {
                sb.Append(cs);
                sb.Append("｜");
            }
            return sb.ToString();
        }

        /// <summary>
        /// 必须以“|”开头并结尾，且必须以“|”作分隔符。
        /// </summary>
        /// <param name="lineText"></param>
        /// <returns></returns>
        private int CellsOfLine(string lineText)
        {
            if (string.IsNullOrWhiteSpace(lineText)) return 0;

            int cells = 0;
            foreach (var c in lineText)
            {
                if (c == '｜' || c == '|') cells++;
            }

            return cells - 1;
        }

    }

    public enum HeaderOrBodyType
    {
        /// <summary>
        /// 表头行。
        /// </summary>
        HeaderLine,
        /// <summary>
        /// 表体行。
        /// </summary>
        BodyLine,
        /// <summary>
        /// 列对齐定义行。
        /// </summary>
        ColumnDifinition,
    }
}
